/*
 * HttpProtocol.h
 *
 */

#ifndef HTTPPROTOCOL_H_
#define HTTPPROTOCOL_H_

#include "HttpRequest.h"
#include "HttpResponse.h"
#include "../../common/Socket.h"
#include <vector>


class HttpProtocol {
	private:
		static const int BODY_BUFFER_SIZE = 512;
		Socket& socket;
		std::vector<char> bodyBuffer;
		HttpRequest* request;
	public:
		/** Crea una instancia asociada a un socket cliente.
		 * @param socket Referencia al socket cliente conectado.
		 */
		HttpProtocol(Socket& socket);

		virtual ~HttpProtocol();

		/**
		 * Devuelve una referencia constante al request recibido.
		 * @throw ParserException En caso que la request este mal formada.
		 * @throw SocketException En caso de fallo en la conexión.
		 */
		const HttpRequest* recvRequest();

		/**
		 * Envia el contenido del response al cliente asociado.
		 * @param response Referencia a la respuesta a en enviar.
		 * @throw SocketException En caso de fallo en la conexión.
		 */
		void sendResponse(HttpResponse& response);
	protected:
		/**
		 * Recibe datos hasta encontrar un fin de linea.
		 * @param line Referencia a cadena donde cargara la linea recibida.
		 * @throw SocketException En caso de fallo en la conexión.
		 */
		void recvLine(std::string& line);

		/**
		 * Recibe datos hasta encontrar fin de encabezados.
		 * @param request HttpRequest donde cargará los encabezados recibidos.
		 * @throw ParserException En caso que algún header este mal formado
		 * @throw SocketException En caso de fallo en la conexión
		 */
		void recvHeaders(HttpRequest* request);

		/**
		 * Recibe un body de tamaño size y lo carga en el request pasado.
		 * @param request Request donde cargará el body recibido.
		 * @param size Tamaño del cuerpo a recibir.
		 * @throw ParserException En caso que la request este mal formada
		 * @throw SocketException En caso de fallo en la conexión
		 */
		void recvBody(HttpRequest* request, size_t size);

		/**
		 * Envía una linea al cliente asociado.
		 * @param line Cadena a enviar.
		 * @throw SocketException En caso de fallo en la conexión
		 */
		void sendLine(const std::string& line);

		/**
		 * Envía los encabezados de un HttpResponse.
		 * @param response HttpResponse del cual enviará los headers.
		 * @throw SocketException En caso de fallo en la conexión
		 */
		void sendHeaders(HttpResponse& response);

		/**
		 * Envía el body al cliente asociado.
		 * @param body Referencia al body a enviar.
		 * @throw SocketException En caso de fallo en la conexión
		 */
		void sendBody(HttpBody& body);

		/**
		 * Maneja la memoria de los request que cree esta clase.
		 * @param request Puntero a un Request en el heap.
		 */
		void setRequest(HttpRequest* request);
};

#endif /* HTTPPROTOCOL_H_ */
